package com.shop.loan.util.doc;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.shop.loan.redis.RedisLockUtil;
import com.shop.loan.redis.RedisUtil;
import com.shop.loan.service.SettingService;
import com.shop.loan.model.entity.ContractByMybatis;
import com.shop.loan.model.entity.SettingByMybatis;
import com.shop.loan.model.vo.ContractCodeVo;
import com.shop.loan.redis.RedisLockUtil;
import com.shop.loan.redis.RedisUtil;
import com.shop.loan.service.SettingService;
import com.shop.loan.util.Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

@Slf4j
@Component
public class ContractDocUtil {

    @Value("${sys.file.path}")
    private String sysFilePath;

    @Resource
    SettingService settingService;

    @Resource
    RedisUtil redisUtil;

    @Resource
    RedisLockUtil redisLockUtil;

    //合同转pdf
    private String contractToPdfKey = "contractToPdfKey";


    /**
     * 替换合同中的code
     *
     * @param contractCodeVo
     */
    public String replaceContractKey(ContractCodeVo contractCodeVo, ContractByMybatis contract) {
        FileOutputStream outStream = null;
        XWPFDocument document = null;
        String exportFilePath = null;
        try {
            if (!contract.getDetail().startsWith("/")) {
                return null;
            }
            SettingByMybatis setting = settingService.getSetting();
            String srcPath = sysFilePath + "/contract/template/" + contract.getType() + "/" + FileUtil.getName(contract.getDetail());
            if (!new File(srcPath).exists()) {
                log.info("合同模版文件为空---正在下载");
                //文件不存在
                HttpUtil.downloadFile(setting.getFileDomain() + contract.getDetail(), srcPath);
            }

            Map<String, String> contentMap = new HashMap<>();
            JSONObject codeJs = JSON.parseObject(JSON.toJSONString(contractCodeVo, SerializerFeature.WriteMapNullValue));
            for (String key : codeJs.keySet()) {
                contentMap.put("${" + key + "}", codeJs.getString(key) == null ? "" : codeJs.getString(key));
            }
            document = new XWPFDocument(new FileInputStream(srcPath));
            // 替换段落中的指定文字
            Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();
            while (itPara.hasNext()) {
                XWPFParagraph paragraph = itPara.next();
                commonCode(paragraph, contentMap);
            }

            // 替换表格中的指定文字
            Iterator<XWPFTable> itTable = document.getTablesIterator();
            while (itTable.hasNext()) {
                XWPFTable table = itTable.next();
                int rcount = table.getNumberOfRows();
                for (int i = 0; i < rcount; i++) {
                    XWPFTableRow row = table.getRow(i);
                    List<XWPFTableCell> cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        //单元格中有段落，得做段落处理
                        List<XWPFParagraph> paragraphs = cell.getParagraphs();
                        for (XWPFParagraph paragraph : paragraphs) {
                            commonCode(paragraph, contentMap);
                        }
                    }
                }
            }
            exportFilePath = sysFilePath + "contract/" + contractCodeVo.getLoanOrderId() + "/contract_" +
                    contractCodeVo.getLoanOrderId() + "_" + contract.getType() + "_" + System.currentTimeMillis() + ".docx";
            File exportFile = new File(exportFilePath);
            if (!exportFile.getParentFile().exists()) {
                exportFile.getParentFile().mkdirs();
            }
            if (!exportFile.exists()) {
                exportFile.createNewFile();
            }
            outStream = new FileOutputStream(exportFilePath);
            document.write(outStream);

//            String pdfPath = sysFilePath + "contract/" + contractCodeVo.getLoanOrderId();
            return exportFilePath;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(Util.GetErrorDetails(e));
        } finally {
            try {
                if (outStream != null) {
                    outStream.close();
                }
                if (document != null) {
                    document.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private void commonCode(XWPFParagraph paragraph, Map<String, String> contentMap) {
        List<XWPFRun> runs = paragraph.getRuns();
        for (XWPFRun run : runs) {
            if (run.getCTR().sizeOfBrArray() < run.getTextPosition()) {
                continue;
            }
            String oneparaString = run.getText(run.getTextPosition());
            if (!StringUtils.hasLength(oneparaString) || !oneparaString.contains("$")) {
                continue;
            }
            for (Map.Entry<String, String> entry :
                    contentMap.entrySet()) {
                oneparaString = oneparaString.replace(entry.getKey(), entry.getValue());
            }
            run.setText(oneparaString, 0);
        }
    }

    /**
     * 文档转pdf（保证同一时间只有一个进程转pdf  10秒内没有转换后 就取消锁）
     *
     * @param docPath
     * @param pdfPath
     */
    public String docToPdf(String docPath, String pdfPath) {
        Jedis jedis = redisUtil.getJedis();
        String lockValue = UUID.randomUUID().toString();
        try {
            while (!redisLockUtil.lock(jedis, contractToPdfKey, lockValue, 10 * 1000L)) {
                Thread.sleep(20);
            }
            String command = "libreoffice --convert-to pdf --outdir " + pdfPath + " " + docPath;
            log.info("文档转pdf  命令开始：{}", command);
            String runResult = RuntimeUtil.execForStr(command);
            log.info("文档转pdf  命令结束：{},结果:{}", command, runResult);
            String pdf = docPath.replace(".docx", ".pdf");
            return pdf;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(Util.GetErrorDetails(e));
        } finally {
            if (jedis != null) {
                redisLockUtil.release(jedis, contractToPdfKey, lockValue);
                jedis.close();
            }
        }
        return null;
    }

}
